home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 258 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  5.3 KB

  1. From: dirk@becker.adviser.com (Dirk Becker)
  2. Message-ID: <v01530500ad38ee830c96@[194.163.74.11]>
  3. X-Original-Date: Sat, 3 Feb 1996 17:51:10 +0100
  4. Path: in1.uu.net!bounce-back
  5. Date: 03 Feb 96 17:22:11 GMT
  6. Approved: fjh@cs.mu.oz.au
  7. Organization: -
  8. Newsgroups: comp.std.c++
  9. X-Sender: dirk@194.163.74.12
  10. Content-Type: text/plain; charset="us-ascii"
  11. Subject: class.union questions
  12. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  13.     iQBFAgUBMROZ5uEDnX0m9pzZAQEB1AF/WVxISufM6sQ04fYfOhDI3Fb7rSvzecsv
  14.     +QUvYRtGliDB8QMAlJXz6Noo1sFrdVnl
  15.     =O7qD
  16.  
  17. Hello, C++ gurus!
  18.  
  19. In Section 9.6.1 Unions [class.union] there is a large collection of
  20. restrictions on the union itself and on candidate member classes.
  21. I would like to ask for reasons of several of them:
  22.  
  23. a)  "A union shall not have base classes. A union shall not be used as
  24.      a base class."
  25.  
  26. This prevents any construction like the following, where one would
  27. like to extend the union contained in some base class:
  28.  
  29. class GenericInterpreter {
  30.     union opcode {
  31.         short tag;
  32.         struct { short tag; short data; } op1;
  33.         struct { short tag; char* data; } op2;
  34.     };
  35. };
  36.  
  37. class SpecialInterpreter : public GenericInterpreter {
  38.     union opcode : public GenericInterpreter::opcode {
  39.         struct { short tag; long  data; } op3;
  40.         struct { short tag; float data; } op4;
  41.     };
  42. };
  43.  
  44. b) "An object of a class with a non-trivial default constructor
  45.     (_class.ctor_), a non-trivial copy constructor (_class.copy_),
  46.     a non-trivial destructor (_class.dtor_), or a non-trivial copy
  47.     assignment operator (_over.ass_, _class.copy_) cannot be a member
  48.     of a union,"
  49.  
  50. This is a major reduction of the restrictions found in ARM, where all
  51. kinds of constructors or assignment operators were excluded. Here is
  52. also a note to give the explanation by the assumption, any member
  53. functions and especially assignments would usually expect a correctly
  54. constructed object.
  55.  
  56. The quoted WP sequence tries its best to exclude virtual function
  57. tables from the union members, which is just fine. But through the
  58. non-trivialness you also exclude _any_ custom make of the copy
  59. constructor and assignment operator.
  60. So you can have any special assignment operator or constructor for
  61. your member objects, any but the most common and useful ones.
  62.  
  63. Another sample:
  64.  
  65. class longlong { ... };
  66. struct opcode {
  67.     short tag;
  68.     union {
  69.         short     op1;
  70.         long      op2;
  71.         longlong  op3;
  72.     } data;
  73. };
  74.  
  75. If you are lucky to have some native long long datatype, then this
  76. would be legal code. If you already had to implement your own
  77. class longlong, now you lost the chance to use it (here).
  78.  
  79. c) "A union can be thought of as a class"
  80.  
  81. Here you accept the implications of 12.8.8 and 12.8.13 on implicitly
  82. defined copy constructor and copy assignment. The already trivial
  83. copy constructor/assignment of the member objects will then result
  84. in one large repetition of copies from and to the same memory locations.
  85. To avoid this behaviour I would strongly recommend to implement your
  86. own copy constructor or assignment whenever you use a union, because a
  87. memberwise copy is usually not desired.
  88.  
  89. Let's combine this with the problems of a) and b):
  90.  
  91. class GenericInterpreter {
  92.     union opcode {
  93.         opcode(const opcode&);               // replace implicitly defined
  94.         opcode& operator = (const opcode&);  // memberwise copy versions
  95.  
  96.         short tag;
  97.         struct { short tag; short data; } op1;
  98.         struct { short tag; char* data; } op2;
  99.     };
  100. };
  101.  
  102. class SpecialInterpreter : public GenericInterpreter {
  103.     union opcode {
  104.         GenericInterpreter::opcode      generic; // error: non-trivial member
  105.         short tag;
  106.         struct { short tag; long  data; } op3;
  107.         struct { short tag; float data; } op4;
  108.     };
  109. };
  110.  
  111. class ValidInterpreter : public GenericInterpreter {
  112.     union opcode {
  113.         // using copy - paste instead of language features
  114.         short tag;
  115.         struct { short tag; short data; } op1;
  116.         struct { short tag; char* data; } op2;
  117.         //
  118.         struct { short tag; long  data; } op3;
  119.         struct { short tag; float data; } op4;
  120.     };
  121. };
  122.  
  123. In my opinion, comparing the copy constructor/assignments to others, they
  124. are only special regarding their use by the implicitly defined memberwise
  125. copy constructor/assignment by outside classes. Here I can't find a reason
  126. why a member's custom copy methods should not be applicable instead.
  127.  
  128. Conclusion, just dreaming:
  129.  I would generally prefer " ... constructors and destructor of member
  130.  objects are ignored, if not explicitly called by the union's ctor/dtor.
  131.  The union's implicit default copy constructor / assignment does a
  132.  binary copy instead of memberwise copy. Objects <containing a vptr>
  133.  cannot be member of a union" - Please pardon my shortcut on vptrs.
  134.  
  135. d) anonymous union
  136.  
  137. Why is there no anonymous struct? This is not only for symmetric reasons,
  138. but anonymous structs inside unions may be as useful as anonymous unions
  139. inside structs.
  140.  
  141.  
  142. Best regards
  143. Dirk
  144.  
  145. ------------------------------------------------------------------
  146. Dirk Becker                                dirk@becker.adviser.com
  147. Harderweg 76, 22549 Hamburg, Germany          Tel. +49 40 80783143
  148. ---
  149. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  150.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  151.   is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
  152.